home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gekkan Dennou Club 145
/
Gekkan Dennou Club - 2000.6 Vol. 145 (Japan).7z
/
Gekkan Dennou Club - 2000.6 Vol. 145 (Japan) (Track 1).bin
/
games
/
spassion
/
source.lzh
/
SOURCE
/
PLAYER.C
< prev
next >
Wrap
Text File
|
2000-03-31
|
17KB
|
524 lines
/*
#include <stdio.h>
#include <iocslib.h>
*/
#include <XSP2lib.H>
#include "SPASSION.H"
#include "PLAYER.H"
#include "SHOT.H"
#include "EFFECT.H"
#include "ENTRY.H"
#include "PRIORITY.H"
#include "BG.H"
#include "SOUND.H"
#include "SUB.H"
#define PLAYER_DIR1 6
#define PLAYER_DIR2 12
#define PLAYER_X_APPEAR ((16- 32) * DOT_RATE) /* 登場時の初期値 */
#define PLAYER_Y_APPEAR ((16+128) * DOT_RATE)
#define PLAYER_VX_APPEAR (4 * DOT_RATE) /* 登場時の移動量 */
#define INIT_DEAD_COUNT 120
#define INIT_DAMAGE_COUNT 40
#define SHORT_LX( x ) (*((short *)(&x))) /*lxの上位ワード*/
#define SHORT_LY( y ) (*((short *)(&y))) /*lyの上位ワード*/
#define CHARGE_TIME 60
#define APP_PT 12
#define SHI_PT 16
/*
* 自機・自弾のデータの初期化
*/
void InitPlayer( PLAYER *player )
{
short i;
player->pt = obj_player+2;
player->info = PALET_PLAYER|PRIORITY_PLAYER;
player->lx = PLAYER_X_APPEAR; /* 座標 */
player->ly = PLAYER_Y_APPEAR; /* 座標 */
player->vx = PLAYER_VX_APPEAR; /* 登場時の移動量 */
player->vy = 0; /* 登場時の移動量 */
player->state = PLAYER_APPEAR; /* プレイヤーの状態 */
player->shot_type = 0; /* ショットの種類 */
player->charge = 0; /* エネルギーチャージ数 */
player->dir = 0; /* 自機の向いている方向 */
player->dead_count = 0; /* 死ぬときのカウンタ ( 0 だと生きている ) */
player->muteki_count = 0; /* 復活後の無敵カウンタ ( 0 だと通常 ) */
player->laser[0] = 0; /* レーザーは出てるか(0だと出てない) */
player->laser[1] = 0;
player->shot_count = 0; /* 連射カウンタ ( 0 だと撃てる ) */
player->a_button_flag = 0; /* A ボタンフラグ */
player->b_button_flag = 0; /* B ボタンフラグ */
player->pointer = 0; /* old_lx,old_lyの要素(オプション用) */
player->score = 0; /* 点数 */
player->charge_sp.info = 0x0400|PRIORITY_PLAYER+1;
player->hit_x = PLAYER_HIT_X; /* 今回は値が一定なので使わない */
player->hit_y = PLAYER_HIT_Y;
/* 前回の座標 */
for(i=0;i<256;i++){
player->old_lx[i] = PLAYER_X_APPEAR;
player->old_ly[i] = PLAYER_Y_APPEAR;
}
/* オプション用のデータを設定 */
player->option_type = DEF;
for(i=0;i<10;i++){
player->option[i].pt = obj_option+1;
player->option[i].info = PALET_PLAYER|PRIORITY_PLAYER;
player->option[i].shot_count = 0; /* 連射カウンタ ( 0 だと撃てる ) */
player->option[i].anim_count = 0; /* アニメーションカウント */
player->option[i].charge_sp.info=0x0400|PRIORITY_PLAYER+1;
}
player->option_charge=0;
game_over_state = GAME_PLAY;
}
/* ------------ 自機移動 ----------- */
void MovePlayer( PLAYER *player )
{
int vx[16]={0, 0, 0, 0,-131072,-92682,-92682, 0, 131072, 92682, 92682,0,0,0,0,0};
int vy[16]={0,-131072, 131072, 0, 0,-92682, 92682, 0, 0,-92682, 92682,0,0,0,0,0};
char joy,key,tr;
short pt_dir=0,p,i,barrier_pt;
short dir,fy[2]={64+16,192+16},y; /*退場時に使う*/
extern SHOTINFO shot_info[SHOT_TYPES][POW_LEVELS];
extern SHOTINFO charge_shot_info;
extern SHOTINFO opt_shot_info[SHOT_TYPES];
void VdispRoutine( void );
#if 0
B_CLR_AL();
B_LOCATE(0,0);
printf("option_charge=%d \n",player->option_charge);
#endif
switch (player->state){
case PLAYER_ALIVE: /* 生きている時 */
joy=GetKey( player->num, player->button_swap );
key=joy&0x0F;
/* 移動量を足す */
player->lx+=(player->vx=vx[key]);
player->ly+=(player->vy=vy[key]);
if( (*((short *)(&player->lx))) < PLAYER_MIN_X )
player->lx = PLAYER_MIN_X<<16;
if( (*((short *)(&player->lx))) > PLAYER_MAX_X )
player->lx = PLAYER_MAX_X<<16;
if( (*((short *)(&player->ly))) < PLAYER_MIN_Y )
player->ly = PLAYER_MIN_Y<<16;
if( (*((short *)(&player->ly))) > PLAYER_MAX_Y )
player->ly = PLAYER_MAX_Y<<16;
player->x = (*((short *)(&player->lx))); /*lxの上位ワード*/
player->y = (*((short *)(&player->ly))); /*lyの上位ワード*/
if( key & KEY_UP ){
if( player->dir > -PLAYER_DIR2-6 )player->dir--;
}else
if( key & KEY_DOWN ){
if( player->dir < PLAYER_DIR2+6 )player->dir++;
}
else{
if( player->dir > 0 )player->dir--;
else player->dir++;
}
if( player->dir > PLAYER_DIR2 ) pt_dir=4;
else if( player->dir > PLAYER_DIR1 )pt_dir=3;
else if( player->dir > -PLAYER_DIR1 )pt_dir=2;
else if( player->dir > -PLAYER_DIR2 )pt_dir=1;
else pt_dir=0;
player->pt=obj_player+pt_dir;
tr=joy&0xF0;
if( tr & B_BUTTON ){ /* Bボタンを押したときの処理 */
/*自機の攻撃*/
if( !player->shot_count ){
( *(shot_info[player->shot_type][player->pow_lev].func_shot_make) )( player,-1 );
player->shot_count=shot_info[player->shot_type][player->pow_lev].interval; /* 秒間 n 発 */
}
/*溜め撃ち*/
if( player->charge == CHARGE_TIME )
( *(charge_shot_info.func_shot_make) )( player,-1 );
/*オプションの攻撃*/
if( player->option_type != MUTEKI ){ /* 無敵中には撃てない */
for(i=0;i<2;i++){
if( !player->option[i].shot_count ){
( *(opt_shot_info[player->option_type].func_shot_make) )( player,i );
player->option[i].shot_count=opt_shot_info[player->option_type].interval; /* 秒間 n 発 */
}
}
}
player->b_button_flag=1;
player->charge=0;
player->charge_sp.pt=0x00;
}else{
/* ボタンが離されてる間は、ショットタイプの切り換えと、溜めを行う */
/*ショットタイプ切り換え*/
if( player->b_button_flag ){
if( player->shot_type == 0 )
player->shot_type = 1;
else
player->shot_type = 0;
/* player->shot_count=0;*/ /* ショットカウンタリセット */
}
player->b_button_flag=0;
/* 溜める */
if( ++player->charge >= CHARGE_TIME ){
short anim_num;
player->charge = CHARGE_TIME;
player->charge_sp.x=player->x+16-8;
player->charge_sp.y=player->y-8;
player->charge_sp.pt=obj_obj+0x1C+(anim_num=(++player->charge_sp.anim_count/4));
if( anim_num > 4 ){
player->charge_sp.pt = obj_obj+0x1C;
player->charge_sp.anim_count = 0;
}
xsp_set_st( &player->charge_sp );
}
}
if(player->shot_count > 0)player->shot_count--;
for(i=0;i<2;i++){
if(player->option[i].shot_count > 0)
player->option[i].shot_count--;
}
/*オプション変更*/
if( tr & A_BUTTON ){
if( player->option_type != MUTEKI ){ /* 無敵のときは切り換えられない */
if( !player->a_button_flag ){
if( ++player->option_type > ATT )
player->option_type=DEF;
player->a_button_flag = 1;
/* player->option[0].shot_count=0;*/ /*注釈取れば連射できる*/
/* player->option[1].shot_count=0;*/ /**/
SetSE(SE_OPTION_CHANGE);
}
}
/* 溜める */
/* if( !player->muteki_count ){*/ /* 無敵のときは溜められない */
if( player->option_type != MUTEKI ){ /* 無敵のときは溜められない */
if( ++player->option_charge >= CHARGE_TIME ){
short anim_num;
player->option_charge = CHARGE_TIME;
player->option[0].charge_sp.x=player->option[0].x;
player->option[0].charge_sp.y=player->option[0].y;
player->option[0].charge_sp.pt=obj_obj+0x1C+(anim_num=(++player->option[0].charge_sp.anim_count/4));
player->option[1].charge_sp.x=player->option[1].x;
player->option[1].charge_sp.y=player->option[1].y;
player->option[1].charge_sp.pt=obj_obj+0x1C+(anim_num=(++player->option[1].charge_sp.anim_count/4));
if( anim_num > 4 ){
player->option[0].charge_sp.pt = obj_obj+0x1C;
player->option[0].charge_sp.anim_count = 0;
player->option[1].charge_sp.pt = obj_obj+0x1C;
player->option[1].charge_sp.anim_count = 0;
}
xsp_set_st( &player->option[0].charge_sp );
xsp_set_st( &player->option[1].charge_sp );
}
}
}else{
player->a_button_flag=0;
if( player->option_charge >= CHARGE_TIME ){
player->muteki_count=60*3;
player->option_type=MUTEKI;
/* player->state=PLAYER_BARRIER;*/
SetSE(SE_MUTEKI);
}
player->option_charge=0;
}
#if 0
/* デバッグ用パワーアップ */
{
static int flag=0;
if( BITSNS(0x03) & BIT(2) ){ /* P キーでレベルアップ */
if( !flag ){
flag=1;
if(++player->pow_lev > 2 )
player->pow_lev=0;
}
}else
flag=0;
}
#endif
/*if(!deb){*/
if( !player->muteki_count ){
if( CheckBGHit(player->x-16+CENTER_X,player->y-16)!=NON_BG ){
player->state=PLAYER_DEAD;
}
}
/*}*/
break;
case PLAYER_APPEAR: /* 自機登場 */
/* 今出現したところ */
if( player->vx==PLAYER_VX_APPEAR ){
if( PLAYER_X < 48 )
player->pt=obj_player+APP_PT+0;
else if( PLAYER_X < 96 )
player->pt=obj_player+APP_PT+1;
else if( PLAYER_X < 144 )
player->pt=obj_player+APP_PT+2;
else if( PLAYER_X < 192 )
player->pt=obj_player+APP_PT+3;
else
player->vx=-2 * DOT_RATE;
}else{
if( PLAYER_X > 160 )
player->pt=obj_player+APP_PT+2;
else if( PLAYER_X > 128 )
player->pt=obj_player+APP_PT+1;
else if( PLAYER_X > 64 )
player->pt=obj_player+APP_PT+0;
else
player->state=PLAYER_ALIVE;
}
player->lx+=player->vx;
player->ly+=player->vy;
player->x = (*((short *)(&player->lx))); /*lxの上位ワード*/
player->y = (*((short *)(&player->ly))); /*lyの上位ワード*/
joy=GetKey( player->num, player->button_swap );
tr=joy&0xF0;
if( !(tr & B_BUTTON) ){
if( ++player->charge >= CHARGE_TIME )
player->charge = CHARGE_TIME;
}
if( tr & A_BUTTON ){ /* Aボタンを押したときの処理 */
player->a_button_flag = 1;
if( ++player->option_charge >= CHARGE_TIME )
player->option_charge=CHARGE_TIME;
}
break;
case PLAYER_LAST: /* オールクリア */
if( play_mode==MODE_1P )y=128+16;
else y=fy[player->num];
switch ( player->dead_count ){
case 2: /* プレイヤーを画面中央に寄せる */
/* 中央までの距離 */
player->gx=player->x-128;if( player->gx < 0 )player->gx*=-1;
player->gy=player->y-y ;if( player->gy < 0 )player->gy*=-1;
/* 移動速度を求める */
dir=calc_direction(player->x, player->y,128,y);
player->vx=vx_tbl[10][dir];
player->vy=vy_tbl[10][dir];
player->dead_count--;
break;
case 1: /* 中央まで来たか? */
if( player->gx > player->gy ){
if( player->vx > 0 ){
if( player->x >= 128 )
player->dead_count=0;
}else{
if( player->x <= 128 )
player->dead_count=0;
}
}else{
if( player->vy > 0 ){
if( player->y >= y )
player->dead_count=0;
}else{
if( player->y <= y )
player->dead_count=0;
}
}
/* 自機の傾きの処理 */
if( player->vy < 0 ){
if( player->dir > -PLAYER_DIR2-6 )player->dir--;
}else if( player->vy > 0 ){
if( player->dir < PLAYER_DIR2+6 )player->dir++;
}else{
if( player->dir > 0 )player->dir--;
else player->dir++;
}
if( player->dir > PLAYER_DIR2 ) pt_dir=4;
else if( player->dir > PLAYER_DIR1 )pt_dir=3;
else if( player->dir > -PLAYER_DIR1 )pt_dir=2;
else if( player->dir > -PLAYER_DIR2 )pt_dir=1;
else pt_dir=0;
player->pt=obj_player+pt_dir;
break;
case 0: /* 自機退場 */
player->vx+=8192;
player->vy=0;
if( PLAYER_X < 128+16 )
player->pt=obj_player+APP_PT+0;
else if( PLAYER_X < 160 )
player->pt=obj_player+APP_PT+1;
else if( PLAYER_X < 192 )
player->pt=obj_player+APP_PT+2;
else if( PLAYER_X < 224 )
player->pt=obj_player+APP_PT+3;
if( (*((short *)(&player->lx)))>PLAYER_MAX_X+60 )
player->state=PLAYER_WAIT;
}
player->lx+=player->vx;
player->ly+=player->vy;
player->x = (*((short *)(&player->lx))); /*lxの上位ワード*/
player->y = (*((short *)(&player->ly))); /*lyの上位ワード*/
break;
/* 待機 */
case PLAYER_WAIT:
player->lx = PLAYER_X_APPEAR; /* 座標 */
player->ly = PLAYER_Y_APPEAR; /* 座標 */
player->vx = PLAYER_VX_APPEAR;
player->vy = 0;
player->muteki_count = 0;
player->option_charge=0;
if( player->option_type==MUTEKI )
player->option_type--;
for(i=0;i<256;i++){
player->old_lx[i]=PLAYER_X_APPEAR;
player->old_ly[i]=PLAYER_Y_APPEAR;
}
return;
break;
/* 死んでいる時 */
case PLAYER_DEAD:
player->option[0].lx=player->option[0].ly=0;
player->option[1].lx=player->option[1].ly=0;
player->pt = obj_player+5+(++player->dead_count)/4;
if( player->pt <= obj_player+5+6 )
xobj_set_st( player );
if( player->dead_count == 1 )
SetSE(SE_PLAYER_EXPL);
if( player->dead_count == 28 ){
MakeEffect(EFFECT_EXPLPLAYER, 0, player->x, player->y);
player->lx = PLAYER_X_APPEAR; /* 座標 */
player->ly = PLAYER_Y_APPEAR; /* 座標 */
player->x = (*((short *)(&player->lx))); /*lxの上位ワード*/
player->y = (*((short *)(&player->ly))); /*lyの上位ワード*/
player->vx = PLAYER_VX_APPEAR;
player->vy = 0;
}
if( player->dead_count > 60 ){
player->muteki_count=60*4;
player->charge=0;
player->option_charge=0;
if( (--player->left)<0 ){ /* 全滅した */
player->left++; /* 0未満にできないので */
player->state = PLAYER_WAIT;
game_state=IN_GAME_OVER;
xsp_vsyncint_on(&VdispRoutine);
}else{
player->pow_lev=0;
player->state = PLAYER_APPEAR;
player->dead_count = 0;
for(i=0;i<256;i++){
player->old_lx[i]=PLAYER_X_APPEAR;
player->old_ly[i]=PLAYER_Y_APPEAR;
}
}
}
return;
break;
}
/* 無敵状態 */
player->info = PALET_PLAYER | PRIORITY_PLAYER;
if( player->muteki_count ){
player->muteki_count--;
player->flash_count++;
/* バリアが沢山残っているので速いフラッシュ */
if (player->muteki_count > 55) {
if (player->flash_count > 1) {
/* player->info = PALET_PLAYER_FLASH | PRIORITY_PLAYER;*/
player->info = 0x0000;
player->flash_count = 0;
}
} else {
/* バリアが少ししかないので遅いフラッシュ */
if (player->flash_count > 5)
/* player->info = PALET_PLAYER_FLASH | PRIORITY_PLAYER;*/
player->info = 0x0000;
if (player->flash_count > 10)
player->flash_count = 0;
if (player->muteki_count <= 0){
if( player->option_type==MUTEKI )
player->option_type--;
/* player->state = PLAYER_ALIVE;*/ /* バリア切れ */
}
}
}
/*オプション*/
if( player->option_anim_count==0 )
player->option_anim_count=4;
else
player->option_anim_count=0;
switch( player->option_type ){
case DEF: /*防御型*/
player->option[0].lx=player->old_lx[p=((player->pointer-4) & 255)];
player->option[0].ly=player->old_ly[p]-48*DOT_RATE;
player->option[1].lx=player->old_lx[p];
player->option[1].ly=player->old_ly[p]+48*DOT_RATE;
break;
case ATT: /*攻撃型*/
player->option[0].anim_count=(player->option[0].anim_count+4)&255;
player->option[0].lx=player->old_lx[(player->pointer-4) & 255]+5*DOT_RATE+vx_tbl[30][player->option[0].anim_count];
player->option[0].ly=player->old_ly[(player->pointer-4) & 255]+ vy_tbl[30][player->option[0].anim_count];
player->option[1].anim_count=(player->option[0].anim_count+128)&255;
player->option[1].lx=player->old_lx[(player->pointer-4) & 255]+5*DOT_RATE+vx_tbl[30][player->option[1].anim_count];
player->option[1].ly=player->old_ly[(player->pointer-4) & 255]+ vy_tbl[30][player->option[1].anim_count];
break;
case MUTEKI: /*自機無敵*/
player->option[0].anim_count=(player->option[0].anim_count+8)&255;
player->option[0].lx=player->old_lx[(player->pointer-4) & 255]+5*DOT_RATE+vx_tbl[29][player->option[0].anim_count];
player->option[0].ly=player->old_ly[(player->pointer-4) & 255]+ vy_tbl[29][player->option[0].anim_count];
player->option[1].anim_count=(player->option[0].anim_count+128)&255;
player->option[1].lx=player->old_lx[(player->pointer-4) & 255]+5*DOT_RATE+vx_tbl[29][player->option[1].anim_count];
player->option[1].ly=player->old_ly[(player->pointer-4) & 255]+ vy_tbl[29][player->option[1].anim_count];
/* シールド */
player->option[2].lx=player->lx+3*DOT_RATE;
player->option[2].ly=player->ly;
player->option[2].x = (*((short *)(&player->option[2].lx))); /*lxの上位ワード*/
player->option[2].y = (*((short *)(&player->option[2].ly))); /*lyの上位ワード*/
if( (barrier_pt=(++player->option[2].anim_count)/4) > 4 ){
player->option[2].anim_count=0;
barrier_pt=0;
}
player->option[2].pt=obj_player+SHI_PT+barrier_pt;
if( player->muteki_count < 60*1 ) /* 制限時間が近づいたら色を変える */
player->option[2].info = 0x033F|PRIORITY_PLAYER;
else
player->option[2].info = 0x043F|PRIORITY_PLAYER;
xobj_set_st( &player->option[2] );
break;
}
for(i=0;i<2;i++){
short x,y;
player->option[i].pt=obj_option+pt_dir/2+player->option_anim_count;
player->option[i].x = (*((short *)(&player->option[i].lx)))-8; /*lxの上位ワード*//*-8は表示位置をずらすため*/
player->option[i].y = (*((short *)(&player->option[i].ly)))-8; /*lyの上位ワード*/
xsp_set_st( &player->option[i] );
/* BGとの当たり判定 */
if( CheckBGHit(x=player->option[i].x-16+8,y=player->option[i].y-16+8)==ERASE_BG )
BreakBG( x, y );
}
player->old_lx[player->pointer]=player->lx;
player->old_ly[player->pointer]=player->ly;
player->pointer++;
player->pointer&=255;
xobj_set_st( player );
}